package com.tuling.echo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * 客户端
 * OP_CONNECT
 * OP_READ
 * OP_WRITE
 * 
 * @author chenhs
 * Created on 2017年12月19日 下午3:39:05
 */
public class EchoClient {
	private int port;
	private Selector selector;
	private ByteBuffer buffer = ByteBuffer.allocate(1024);
	
	public static void main(String[] args) throws IOException {
		new EchoClient(8000).start();
	}
	
	public EchoClient(int port) {
		this.port = port;
	}

	public void start() throws IOException {
		SocketChannel socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);
		
		this.selector = Selector.open();
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
		socketChannel.connect(new InetSocketAddress(port));
		
		while (true) {
			selector.select();
			Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
			while (keys.hasNext()) {
				SelectionKey key = (SelectionKey) keys.next();
				if(key.isConnectable()) {
					handleConnect(key);
				} else if (key.isReadable()) {
					handleRead(key);
				} else if (key.isWritable()) {
					handleWrite(key);
				}
				
				keys.remove();
			}
		}
	}
	
	private void handleWrite(SelectionKey key) throws IOException {
		buffer.clear();
		SocketChannel socketChannel = (SocketChannel) key.channel();
		String message = "#message from client#";
		buffer.put(message.getBytes());
		buffer.flip();
		socketChannel.write(buffer);
		System.out.println("Client send message to server :" + message);
		socketChannel.register(selector, SelectionKey.OP_READ);
	}
	
	private void handleRead(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		buffer.clear();
		int length = socketChannel.read(buffer);	//read data from channel
		if (length > 0) {
			String serverMessage = new String(buffer.array(), 0, length);
			System.out.println("Client received message from server :: " + serverMessage);
			socketChannel.register(selector, SelectionKey.OP_WRITE);
		}
	}
	
	private void handleConnect(SelectionKey key) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		if(socketChannel.isConnectionPending()) {
			socketChannel.finishConnect();
			buffer.clear();
			buffer.put("Message from client".getBytes());
			buffer.flip();
			socketChannel.write(buffer);
		}
		socketChannel.register(selector, SelectionKey.OP_READ);
	}
}
